// 属性直接赋值来实现单例，编译器帮我们自动生成了个静态只读变量
// public static Singleton Instance { get; } = new Singleton();
// c#6.0之前无法使用自动属性实现单例，需要双重检查锁定lock保证单例线程安全
public class DeviceManager
{

    // 用于同步的锁对象
    private static readonly object _lock = new();
    // 可空的单例实例字段，保存单例实例
    private static DeviceManager? _instance;
    // 防止多个线程同时创建实例,避免每次访问都加锁
    public static DeviceManager Instance
    {
        get
        {
            // 第一次检查实例是否为 null
            if (_instance == null)
            {
                // 锁定代码块，确保线程安全。
                // 两个线程同时进入代码块时，只有一个线程能够创建实例，等待另一个结束才能执行
                lock (_lock)
                {
                    // 防止多个线程通过第一次检查后重复创建实例
                    // 因为线程可能在等待锁的过程中，其他线程已经创建了实例
                    if (_instance == null)
                    {
                        // 创建单例实例
                        _instance = new DeviceManager();
                    }
                }
            }
            return _instance;
        }
    }
    // 私有构造函数，防止外部实例化
    private DeviceManager() { }
}
// 线程A进入get方法
// 线程B进入get方法

// 线程A: 第一次检查 _instance == null → true
// 线程B: 第一次检查 _instance == null → true

// 线程A: 获取锁成功，进入lock块
// 线程B: 尝试获取锁，被阻塞，等待线程A释放锁

// 线程A: 第二次检查 _instance == null → true
// 线程A: 创建实例 _instance = new DeviceManager()
// 线程A: 释放锁

// 线程B: 获取锁成功，进入lock块
// 线程B: 第二次检查 _instance == null → false（实例已存在）
// 线程B: 跳过创建，释放锁

// 线程A和线程B都返回同一个实例